package com.blog.oguzhan.soapui.utils.datasource;

import java.io.FileNotFoundException;
import java.util.Map;
import java.util.TreeMap;

import com.eviware.soapui.model.testsuite.TestCase;
import com.eviware.soapui.model.testsuite.TestCaseRunContext;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStep;

public class DatasourceFactory {

	private static final Map<String, Datasource<?>> LOOKUP_TABLE = new TreeMap<String, Datasource<?>>();
	
	/**
	 * For Backward Compatibility
	 * */
	public static Datasource<?> getDatasource(TestCaseRunContext ctx, String sourcePath) throws FileNotFoundException {
		try {
			return getDatasource(ctx, DatasourceType.RAW_FILE_DATASOURCE, sourcePath);
		} catch (FileNotFoundException e) {
			throw e;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public static Datasource<?> getDatasource(TestCaseRunContext ctx, DatasourceType datasourceType, String... parameters) throws Exception {
		TestCase testCase = ctx.getTestCase();
		TestStep testStep = ctx.getCurrentStep();
		String name = testStep.getName();
		Object key = getKey(testCase, name);
		if (LOOKUP_TABLE.containsKey(key)) {
			Datasource<?> ds = LOOKUP_TABLE.get(key);
			if (!ds.isBroken()) {
				return ds;
			}
			else {
				LOOKUP_TABLE.remove(key);
			}
		}
		
		Datasource<?> newDatasource = null;
		switch (datasourceType) {
		case RAW_FILE_DATASOURCE:
			newDatasource = new RawFileDatasource(name, parameters[0]); 
			break;
		case DERBY_DATASOURCE:
			newDatasource = new DerbyDatasource<Iterable<?>>(name, parameters[0], parameters[1], parameters[2]);
			break;
		case MYSQL_DATASOURCE:
			newDatasource = new MysqlDatasource<Iterable<?>>(name, parameters[0], parameters[1], parameters[2]);
			break;
		case ORACLE_DATASOURCE:
			newDatasource = new OracleDatasource<Iterable<?>>(name, parameters[0], parameters[1], parameters[2], parameters[3], parameters[4], parameters[5]);
			break;
		default: 
			return null;
		}
		 
		LOOKUP_TABLE.put((String) getKey(testCase, name), newDatasource);
		return newDatasource;
	}
	
	public static DatasourceLoop getDatasourceLoop(TestCaseRunContext ctx, String datasourceName) throws Exception {
		TestCaseRunner testRunner = ctx.getTestRunner();
		TestCase testCase = ctx.getTestCase();
		Datasource<?> datasource = LOOKUP_TABLE.get(getKey(testCase, datasourceName));
		if (datasource != null) {
			DatasourceLoop datasourceLoop = datasource.getDatasourceLoop();
			if (datasourceLoop != null) {
				return datasourceLoop;
			}
			else {
				return new DatasourceLoop(testCase, testRunner, datasource);
			}
		}
		else {
			throw new Exception("System couldn't find datasource. " + datasourceName);
		}
	}

	private static Object getKey(TestCase testCase, String datasourceName) {
//		System.out.println(testCase.getName() + testCase.toString() + datasourceName);
		return testCase.getName() + testCase.toString() + datasourceName;
	}

	public static Datasource<?> getDatasource(TestCase testCase, String name) {
		Object key = getKey(testCase, name);
		return LOOKUP_TABLE.get(key);
	}

	public static void removeDatasource(TestCase testCase, String name) {
		Object key = getKey(testCase, name);
		LOOKUP_TABLE.remove(key);
	}
	
	public static String getLookupMapToString() {
		return LOOKUP_TABLE.toString();
	}
}
